/**
 @file sys_tsingma_mac.h

 @author  Copyright (C) 2011 Centec Networks Inc.  All rights reserved.

 @date 2017-12-29

 @version v2.0

*/

#ifndef _SYS_TMM_MAC_H
#define _SYS_TMM_MAC_H
#ifdef __cplusplus
extern "C" {
#endif

/****************************************************************
 *
 * Header Files
 *
 ***************************************************************/
#include "sys_usw_mac.h"

/****************************************************************
*
* Defines and Macros
*
****************************************************************/
#define TXQM_INNER_MAC_ID(mac_id) ((mac_id) % SYS_TMM_MAX_MAC_NUM_PER_TXQM)
#define MCPCS_IS_X16_A(pcs_idx) ((pcs_idx) % 16 < 8)

#define SYS_TMM_HS_MACID_NUM_PER_DP 80
#define SYS_TMM_MAC_CALENDAR_MULTI_FACTOR         1000
#define SYS_TMM_MAC_CALENDAR_BUS_WIDTH_EPE        192
#define SYS_TMM_MAC_CALENDAR_BUS_WIDTH_TX         96
#define SYS_TMM_MAC_CALENDAR_CLK_MF        ((500 == p_usw_datapath_master[lchip]->core_plla) ? 450 : 1050)
#define SYS_TMM_MAC_CALENDAR_ROUND_ID      40    /*idle/sgmii/2g5/qsgmii port id*/

#define SYS_TMM_JUDGE_HS_BY_MACID(mac_id) ((((mac_id) % SYS_TMM_MAX_MAC_NUM_PER_DP) < SYS_TMM_HS_MACID_NUM_PER_DP) ? \
                                            TRUE : FALSE)

#define SYS_TMM_GET_QSGMII_INTERNAL_MAC_IDX(mac_id, internal_mac_idx) do {\
    if(31 >= mac_id)                            {internal_mac_idx = mac_id % 4;}\
    else if((40 <= mac_id) && (71 >= mac_id))   {internal_mac_idx = (mac_id - 40) % 4;}\
    else if((160 <= mac_id) && (191 >= mac_id)) {internal_mac_idx = (mac_id - 160) % 4;}\
    else if((200 <= mac_id) && (231 >= mac_id)) {internal_mac_idx = (mac_id - 200) % 4;}\
    else                                        {internal_mac_idx = SYS_TMM_USELESS_ID8;}\
} while(0)

#define SYS_TMM_CPUMAC_GET_INTERNAL_MAC_ID(mac_id, internal_mac_id) do {\
    switch(mac_id)\
    {\
        case 320:\
            internal_mac_id = 0;\
            break;\
        case 321:\
            internal_mac_id = 1;\
            break;\
        case 322:\
            internal_mac_id = 2;\
            break;\
        case 323:\
        default:\
            internal_mac_id = 3;\
            break;\
    }\
} while(0)

#define GET_SPEED_STR_BY_ENUM(speed_mode, speed_str)\
{\
    switch (speed_mode)                           \
    {                                             \
    case CTC_PORT_SPEED_1G:                       \
         sal_strncpy(speed_str, "1000M", 6);      \
         break;                                   \
    case CTC_PORT_SPEED_100M:                     \
         sal_strncpy(speed_str, "100M", 5);       \
         break;                                   \
    case CTC_PORT_SPEED_10M:                      \
         sal_strncpy(speed_str, "10M", 4);        \
         break;                                   \
    case CTC_PORT_SPEED_2G5:                      \
         sal_strncpy(speed_str, "2.5G", 5);       \
         break;                                   \
    case CTC_PORT_SPEED_10G:                      \
         sal_strncpy(speed_str, "10G", 4);        \
         break;                                   \
    case CTC_PORT_SPEED_20G:                      \
         sal_strncpy(speed_str, "20G", 4);        \
         break;                                   \
    case CTC_PORT_SPEED_40G:                      \
         sal_strncpy(speed_str, "40G", 4);        \
         break;                                   \
    case CTC_PORT_SPEED_100G:                     \
         sal_strncpy(speed_str, "100G", 5);       \
         break;                                   \
    case CTC_PORT_SPEED_5G:                       \
         sal_strncpy(speed_str, "5G", 3);         \
         break;                                   \
    case CTC_PORT_SPEED_25G:                      \
         sal_strncpy(speed_str, "25G", 4);        \
         break;                                   \
    case CTC_PORT_SPEED_50G:                      \
         sal_strncpy(speed_str, "50G", 4);        \
         break;                                   \
    case CTC_PORT_SPEED_200G:                     \
         sal_strncpy(speed_str, "200G", 5);       \
         break;                                   \
    case CTC_PORT_SPEED_400G:                     \
         sal_strncpy(speed_str, "400G", 5);       \
         break;                                   \
    }                                             \
}

#define GET_FEC_STR_BY_ENUM(fec_type, fec_str)   \
{\
    switch (fec_type)                             \
    {                                             \
    case CTC_PORT_FEC_TYPE_NONE:                  \
         sal_strncpy(fec_str, "None", 5);         \
         break;                                   \
    case CTC_PORT_FEC_TYPE_RS:                    \
         sal_strncpy(fec_str, "Rs", 3);           \
         break;                                   \
    case CTC_PORT_FEC_TYPE_BASER:                 \
         sal_strncpy(fec_str, "Base-R", 7);       \
         break;                                   \
    case CTC_PORT_FEC_TYPE_RS528:                 \
         sal_strncpy(fec_str, "Rs528", 6);        \
         break;                                   \
    case CTC_PORT_FEC_TYPE_RS544:                 \
         sal_strncpy(fec_str, "Rs544", 6);        \
         break;                                   \
    case CTC_PORT_FEC_TYPE_RS272:                 \
         sal_strncpy(fec_str, "Rs272", 6);        \
         break;                                   \
    case CTC_PORT_FEC_TYPE_FC2112:                \
         sal_strncpy(fec_str, "Fc2112", 7);       \
         break;                                   \
    }                                             \
}

#define GET_IFTYPE_STR_BY_ENUM(if_type, iftype_str)\
{\
    switch (if_type)                              \
    {                                             \
    case CTC_PORT_IF_SGMII:                       \
         sal_strncpy(iftype_str, "SGMII", 6);     \
         break;                                   \
    case CTC_PORT_IF_2500X:                       \
         sal_strncpy(iftype_str, "2500X", 6);     \
         break;                                   \
    case CTC_PORT_IF_QSGMII:                      \
         sal_strncpy(iftype_str, "QSGMII", 7);    \
         break;                                   \
    case CTC_PORT_IF_XFI:                         \
         sal_strncpy(iftype_str, "XFI", 4);       \
         break;                                   \
    case CTC_PORT_IF_KR:                          \
         sal_strncpy(iftype_str, "KR", 3);        \
         break;                                   \
    case CTC_PORT_IF_CR:                          \
         sal_strncpy(iftype_str, "CR", 3);        \
         break;                                   \
    case CTC_PORT_IF_KR2:                         \
         sal_strncpy(iftype_str, "KR2", 4);       \
         break;                                   \
    case CTC_PORT_IF_CR2:                         \
         sal_strncpy(iftype_str, "CR2", 4);       \
         break;                                   \
    case CTC_PORT_IF_KR4:                         \
         sal_strncpy(iftype_str, "KR4", 4);       \
         break;                                   \
    case CTC_PORT_IF_CR4:                         \
         sal_strncpy(iftype_str, "CR4", 4);       \
         break;                                   \
    case CTC_PORT_IF_FX:                          \
         sal_strncpy(iftype_str, "100BASEFX", 10);\
         break;                                   \
    case CTC_PORT_IF_KR8:                         \
         sal_strncpy(iftype_str, "KR8", 4);       \
         break;                                   \
    case CTC_PORT_IF_CR8:                         \
         sal_strncpy(iftype_str, "CR8", 4);       \
         break;                                   \
    }                                             \
}




enum tmm_sys_func_intr_feature_e
{
    TMM_FUNC_INTR_AN_COMPLETE = 0,     //funcIntrHssL[]gpo0ChgMcu
    TMM_FUNC_INTR_AN_LINK_GOOD,        //funcIntrHssL[]AnLinkGoodMcu
    TMM_FUNC_INTR_AN_PAGE_RX,          //funcIntrHssL[]AnPageRxMcu
    TMM_FUNC_INTR_RX_UPDATE_REQ,       //funcIntrHssL[]RxUpdateReqMcu
    TMM_FUNC_INTR_TRAIN_FAIL,          //funcIntrHssL[]TrainFailMcu
    TMM_FUNC_INTR_TRAIN_OK,            //funcIntrHssL[]TrainOkMcu
    TMM_FUNC_INTR_BUTT
};
typedef enum tmm_sys_func_intr_feature_e tmm_sys_func_intr_feature_t;

enum sys_item_config_flag_e
{
    ITEM_NO_WRITE,      //no write in hard table
    ITEM_WRITE_CONST,   //write in constant table id & field id
    ITEM_WRITE_VARY,    //write in constant table id, but field id varies when doing IOW
    ITEM_WRITE_ON_READ, //write value based on primitive read value, e.g. McPcsX16LanesTxPam4EnCfg_cfgTxChanIsPam4Bmp_f
    ITEM_WRITE_BUTT
};
typedef enum sys_item_config_flag_e sys_item_config_flag_t;

enum sys_config_list_offset_type_e
{
    OFFSET_TYPE_1,                  //offset = 0
    OFFSET_TYPE_TXQM_MAC_ID,        //offset = ((mac_id) % 40)
    OFFSET_TYPE_PCS_ID,             //offset = port_attr->pcs_idx % (8 or 16)
    OFFSET_TYPE_LOGICAL_LANE_ID,    //offset = port_attr->pcs_idx % (8 or 16) + i
    OFFSET_TYPE_PHYSICAL_LANE_ID,   //offset = serdes_id[i] % (8 or 16)
    OFFSET_TYPE_LOGICAL_LANE_ID_X16AB,    //offset = port_attr->pcs_idx % 8 + i  for X16 A/B divided tables
    OFFSET_TYPE_PHYSIC_LANE_ID_X16AB,   //offset = serdes_id[i] % 8  for X16 A/B divided tables
    OFFSET_TYPE_BUTT
};
typedef enum sys_config_list_offset_type_e sys_config_list_offset_type_t;

enum sys_config_list_tbl_idx_type_e
{
    INDEX_TYPE_0_0,                 //index = 0
    INDEX_TYPE_TXQMID_0,            //index = DRV_INS(port_attr->txqm_id, 0)
    INDEX_TYPE_TXQMID_MACID,        //index = DRV_INS(port_attr->txqm_id, (port_attr->mac_id % 40))
    INDEX_TYPE_TXQMID_PCSID,        //index = DRV_INS(port_attr->txqm_id, (port_attr->pcs_idx % pcs_lane_num))
    INDEX_TYPE_PCSXIDX_0,           //index = DRV_INS(pcs_x8_x16_index, 0)
    INDEX_TYPE_PCSXIDX_PCSID,       //index = DRV_INS(pcs_x8_x16_index, (port_attr->pcs_idx % pcs_lane_num))
    INDEX_TYPE_BUTT
};
typedef enum sys_config_list_tbl_idx_type_e sys_config_list_tbl_idx_type_t;

enum sys_config_list_value_type_e
{
    VALUE_TYPE_NORMAL,              //normal value
    VALUE_TYPE_TXQM_INNER_MAC_ID,   //value = (mac_id) % 40    mac_id in one txqm
    VALUE_TYPE_PCS_ID,              //value = port_attr->pcs_idx % (8 or 16)
    VALUE_TYPE_PCS_ID_BMP,          //value bitmap position is port_attr->pcs_idx % (8 or 16)
    VALUE_TYPE_LOGICAL_LANE_ID,     //value = port_attr->pcs_idx % (8 or 16) + i
    VALUE_TYPE_PCS_L_ID,            //value = (0 ~ logic_lane_num), max 8
    VALUE_TYPE_PCSX_BASED_1,        //value = is_pcs_x16 ? 0 : 1
    VALUE_TYPE_MAC_ID_BMP,          //value bitmap position (port_attr->mac_id % 40) set 1
    VALUE_TYPE_BUTT
};
typedef enum sys_config_list_value_type_e sys_config_list_value_type_t;

enum sys_mode_with_fec_e
{
    XFI_FC2112,
    XXVG_FC2112,
    XXVG_RS528,
    XLG_FC2112,
    LG_R2_RS528,
    LG_R2_RS544,
    LG_R1_RS528,
    LG_R1_RS544,
    LG_R1_RS272,
    CG_R4_RS528,
    CG_R4_RS544,
    CG_R2_RS528,
    CG_R2_RS544,
    CG_R2_RS272,
    CCG_R4_RS544,
    CCG_R4_RS272,
    CDG_R8_RS544,
    CDG_R8_RS272,
    MAX_MODE_FEC
};
typedef enum sys_mode_with_fec_e sys_mode_with_fec_t;

enum sys_mcmac_config_list_item_e
{
    McMac_cfgMcMacTxSpeed,
    McMac_cfgTxAmInsertEn,
    McMac_cfgTxAmInterval,
    McMac_cfgMcMacTxIpgDelEn,
    McMac_cfgTxRsFecEn,
    McMac_cfgTxRsFecMode,
    McMac_cfgTxChanIdLane,
    McMac_TxPortMap,
    McMac_RxChanMap,
    McMac_cfgTxCreditThrd,
    McMac_cfgMcMacSgmiiTxNotUsePortMap,
    McMac_cfgMcMacMacTxSoftReset,
    McMac_cfgMcMacTxThreshold,
    McMac_cfgMcMacMiiSgmiiMod,
    McMac_cfgMcMacMiiQsgmiiMod,
    McMac_cfgMiiRxSampleCnt,
    McMac_cfgMcMacTxReplicateCnt,
    McMac_cfgMcMacMiiRxBuffMaxDepth,
    McMac_cfgMcMacRxUseHataTsEn,
    McMac_cfgMcMacPmInterval,
    McMac_cfgMcMacMacTxWaitCaptureTs,
    McHata_cfgHataRsFecMode,
    McMac_cfgMcMacMiiRxForceFault,
    McMac_cfgMcMacMiiRxLDForceFault,
    McMac_TOTAL_CNT
};
typedef enum sys_mcmac_config_list_item_e sys_mcmac_config_list_item_t;

enum sys_mcpcs_config_list_item_e
{
    McPcs_logic_lane_num,
    McPcs_SoftRstRxMcFec,
    McPcs_SoftRstTxMcFec,
    McPcs_LaneInit,
    McPcs_cfgRxGearboxMode,
    McPcs_cfgRxChanId,
    McPcs_cfgRxSpeed,
    McPcs_cfgRxDskMaxAddr,
    McPcs_cfgRxLaneswapId,
    McPcs_cfgRxAmInterval,
    McPcs_cfgRxIsPam4,
    McPcs_cfgRxSelRsFec,
    McPcs_cfgRxSelFcFec,
    McPcs_cfgRxFecMode,
    McPcs_cfgTxChanId,
    McPcs_cfgTxLaneId,
    McPcs_cfgTxPcsMode,
    McPcs_cfgTxChanIsPam4,
    McPcs_cfgTxGearboxMode,
    McPcs_cfgTxBufThrd,
    McPcs_cfgTxFifoAFullThrd,
    McPcs_cfgTxRsFecModeSel,
    McPcs_resetQsgmii_resetCore,
    McPcs_cfgSgmii_unidirectionEn,
    McPcs_cfgSgmii_anEnable,
    McPcs_cfgQsgmiiSgmii_unidirectionEn,
    McPcs_cfgQsgmiiSgmii_anEnable,
    McPcs_cfgQsgmiiSgmii_anegMode,
    McPcs_cfgQsgmii_cfgTxCreditThrd,
    McPcs_cfgQsgmii_reAlignEachEn,
    McPcs_cfgTxDoneMode,
    McPcs_cfgTxPrimingThrd,
    McPcs_cfgRxSgmiiMode,
    McPcs_SgmiiAsyncFifo,
    McPcs_TOTAL_CNT
};
typedef enum sys_mcpcs_config_list_item_e sys_mcpcs_config_list_item_t;

enum sys_macpcs_config_property_type_e
{
    MACPCS_CFG_INIT,
    MACPCS_CFG_REMAP,
    MACPCS_CFG_SPEED,
    MACPCS_CFG_BUTT
};
typedef enum sys_macpcs_config_property_type_e sys_macpcs_config_property_type_t;

enum sys_macpcs_config_e
{
    MAC,
    PCS_X8,
    PCS_X16,
    MACPCS_BUTT
};
typedef enum sys_macpcs_config_e sys_macpcs_config_t;

enum sys_calendar_check_ds_xpipe_e
{
    SYS_CAL_CHECK_DS,
    SYS_CAL_CHECK_XPIPE,
    SYS_CAL_CHECK_BUTT
};
typedef enum sys_calendar_check_ds_xpipe_e sys_calendar_check_ds_xpipe_t;


struct sys_macpcs_config_item_s
{
    uint32 cfg_flag;                        //judge if this item need writting
    uint32 table_id;                        //table id
    uint32 field_id_num;                    //field id / value number in one item
    uint32 field_id[SYS_MAC_MAX_LANE_NUM];  //field id
    uint32 value[SYS_MAC_MAX_LANE_NUM];     //item value
    uint32 index;                           //IOR/W index
    uint32 ins;                             //for debug
    uint32 entry;                           //for debug
};
typedef struct sys_macpcs_config_item_s sys_macpcs_config_item_t;



typedef struct {
    uint8 logic_serdes_id;
    uint8 src_mode;
    uint8 dst_mode;
    uint8 ovclk_flag;
    uint8 dst_lport_idx; //related lport list index, the lport using this serdes after dyn switch will be recorded
}sys_tmm_ds_target_serdes_t;

typedef struct {
    uint8 serdes_list_idx;    //related serdes list index
    uint8 relate_flag;      //sys_ds_lport_serdes_old_new_t
}sys_tmm_ds_lport_serdes_relate_t;

typedef struct {
    uint16 lport;
    uint16 chan_id;  //old lport chan id if upt_flag is DROP; else new lport chan id
    uint8  upt_flag; //sys_ds_lport_upt_flag_t
    uint8  serdes_relate_num;
    sys_tmm_ds_lport_serdes_relate_t  serdes_relate[SYS_MAC_MAX_LANE_NUM];
}sys_tmm_ds_target_lport_t;

struct sys_tmm_ds_target_attr_s
{
    uint8 serdes_num;
    sys_tmm_ds_target_serdes_t serdes_list[SYS_DATAPATH_DS_MAX_SERDES_NUM];
    uint32 lport_num;
    sys_tmm_ds_target_lport_t lport_list[SYS_DATAPATH_DS_MAX_PORT_NUM];
    uint8 remap_flag;
    sys_qos_shape_profile_t shp_profile[SYS_DATAPATH_DS_MAX_PORT_NUM];
};
typedef struct sys_tmm_ds_target_attr_s sys_tmm_ds_target_attr_t;

typedef struct {
    uint8 physic_serdes_id; //0~95, 0xff means no physical serdes
    uint8 physic_lane; //0~7, 0xff means no physical lane
    uint8 physic_serdes_old; //0~95, 0xff means no physical serdes
    uint8 change_flag; //0~no change 1~change
}sys_tmm_logic_physic_remap_elem_t;

typedef struct {
    uint8 hss_id;
    sys_tmm_logic_physic_remap_elem_t logic_lane[8];
}sys_tmm_logic_physic_remap_t;

typedef struct {
    uint32 portid_order[SYS_TMM_MAX_MAC_NUM_PER_TXQM];/*interval,per port*/
    uint32 num[SYS_TMM_MAX_MAC_NUM_PER_TXQM];/*select num ,per port*/
    uint32 first_cal_record[SYS_TMM_MAX_MAC_NUM_PER_TXQM];/*record the index first select*/
}sys_mac_cal_heap_t;

/****************************************************************************
 *
* Function
*
*****************************************************************************/

int32
sys_tmm_mac_get_port_capability(uint8 lchip, uint16 lport, sys_datapath_lport_attr_t** p_port);

/*external property*/
extern int32
sys_tmm_mac_get_link_up(uint8 lchip, uint16 lport, uint32* p_is_up, uint32 is_port);

extern int32
sys_tmm_mac_set_property(uint8 lchip, uint16 lport, ctc_port_property_t port_prop, uint32 value);

extern int32
sys_tmm_mac_get_property(uint8 lchip, uint16 lport, ctc_port_property_t port_prop, uint32* p_value);

extern int32
sys_tmm_mac_set_interface_mode(uint8 lchip, uint16 lport, ctc_port_if_mode_t* if_mode);

extern int32
sys_tmm_mac_get_capability(uint8 lchip, uint16 lport, ctc_port_capability_type_t type, void* p_value);

extern int32 sys_tmm_mac_init(uint8 lchip);

extern int32 sys_tmm_set_mac_calendar(uint8 lchip, uint8 dp_id, uint8 txqm_id);

extern int32 sys_tmm_mac_get_txqm_bandwidth(uint8 lchip, uint8 txqm_id, uint32* p_bandwidth);

extern int32 sys_tmm_dynamic_switch_port_id_normalize(uint8 lchip, uint16 lport, uint8 mode, uint16* p_lport_nml);

extern int32 sys_tmm_mac_dynamic_switch_proc(uint8 lchip, uint16 lport, ctc_port_if_mode_t* if_mode);

extern int32 _sys_tmm_mac_set_mac_en(uint8 lchip, uint16 lport, uint8 enable);

extern int32 _sys_tmm_mac_set_mcpcs_config(uint8 lchip, uint16 lport, ctc_chip_serdes_mode_t mode,
                                                     ctc_port_fec_type_t fec_type, uint8 cfg_prop_type);

extern int32 _sys_tmm_mac_set_mcmac_config(uint8 lchip, uint16 lport, ctc_chip_serdes_mode_t mode,
                                                     ctc_port_fec_type_t fec_type, uint8 cfg_prop_type);
extern int32 sys_tmm_cpumac_get_lport_info_by_inner_idx(uint8 lchip, uint8 inner_idx, uint16* lport, uint8 *is_network);
extern int32 _sys_tmm_cpumac_get_link_up(uint8 lchip, uint16 lport, uint32* p_is_up, uint32 is_port);

extern int32 _sys_tmm_cpumac_set_hss_tx_reset(uint8 lchip, uint8 pcs_idx, uint8 lane_num, uint32 val_rst, uint8 swap_flag);

extern int32 sys_tmm_dynamic_switch_para_check(uint8 lchip, uint8 logic_serdes_id, uint8 dst_mode, uint8 dst_ovclk, uint8* p_dup_flag, uint8 remap_flag);

extern int32 _sys_tmm_datapath_dynamic_switch_get_info(uint8 lchip, uint8 logic_serdes_id,
    uint8 src_mode, uint8 dst_mode, sys_tmm_ds_target_attr_t *target, uint16 overclocking_speed);

extern int32 _sys_tmm_mac_set_interface_mode(uint8 lchip, uint8 dst_mode, sys_tmm_ds_target_attr_t *p_ds_attr);

extern uint8 sys_tmm_dynamic_switch_judge_remap(uint8 lchip, uint8 logic_serdes_id, uint8 dst_mode);

extern int32 sys_tmm_dynamic_switch_logic_1_2_swap(uint8 lchip, uint8 logic_serdes_raw);

extern int32 _sys_tmm_cpumac_set_mac_en(uint8 lchip, uint32 lport, uint8 enable);

extern int32 sys_tmm_mac_dynamic_switch_remap_proc(  uint8 lchip, uint8 dst_mode, uint8 logic_serdes_id, uint16 overclocking_speed);

extern int32 sys_tmm_mac_set_serdes_map(uint8 lchip, void* p_data);
#ifdef __cplusplus
}
#endif

#endif

